package br.com.simora.http;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Named;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Tidy;
import org.xml.sax.InputSource;

@Named("recuperador")
public class RecuperadorInformacoes {
	public XPath xpath = null;
	public Document document;
	public String contentType;
	private String tipo;
	private Pagina pagina;
	
	private HttpTools tools = new HttpTools();
	
	public void setUrl(String url, String tipo){
		pagina = tools.getHTML(url);
		//System.out.println(pagina.getConteudo());
		this.tipo = tipo;
		if("xml".equals(tipo)){
			converteXmlParaDocument(pagina.getConteudo());
		}
		
		if("html".equals(tipo)){
			converteHtmlParaDocument(pagina.getConteudo());
		}
	}
	
	public void setUrlPost(String url, String tipo, String parametros){
		pagina = tools.postHTML(url, parametros);
		this.tipo = tipo;
		if("xml".equals(tipo)){
			converteXmlParaDocument(pagina.getConteudo());
		}
		
		if("html".equals(tipo)){
			converteHtmlParaDocument(pagina.getConteudo());
		}
	}
	
	public RecuperadorInformacoes(){}
	
	public RecuperadorInformacoes(String url, String tipo){
		pagina = tools.getHTML(url);
		if("xml".equals(tipo)){
			converteXmlParaDocument(pagina.getConteudo());
		}
		
		if("html".equals(tipo)){
			converteHtmlParaDocument(pagina.getConteudo());
		}
	}
	
	private void converteParaDocument(String docCru, String fileType){
		document = null;
		ByteArrayInputStream stream = null;
		ByteArrayOutputStream log = null;
		PrintWriter logpw = null;

		try {
			stream = new ByteArrayInputStream( docCru.getBytes() );
			log = new ByteArrayOutputStream();
			logpw = new PrintWriter( log );
			Tidy t = new Tidy();
			t.setLiteralAttribs(true);
			t.setUpperCaseTags( true );
			t.setUpperCaseAttrs( true );

			if(fileType.equals("html")){
				t.setXHTML( true );
			}else if(fileType.equals("xml")){
				t.setXmlOut( true );
			}

			t.setErrout( logpw );
			document = t.parseDOM( stream, null );
		} catch ( Exception ex ) {
			ex.printStackTrace();
		} finally {
			if ( logpw != null ) try { logpw.close(); } catch ( Exception ignore ) { }
			if ( log != null ) try { log.close(); } catch ( Exception ignore ) { }
			if ( stream != null ) try { stream.close(); } catch ( Exception ignore ) { }
		}
	}

	private Document converteHtmlParaDocument(String html) {
		converteParaDocument(html, "html");
		return document;
	}

	private Document converteXmlParaDocument(String xml) {
		converteParaDocument(xml, "xml");
		return document;
	}

	private  XPath getXPath() {
		if ( xpath == null ) {
			XPathFactory factory = XPathFactory.newInstance();
			xpath = factory.newXPath();
		}
		return xpath;
	}

	private String getXpathHtml(String xPath) throws Exception {
		try {
			XPath xp = getXPath();
			String resultado = null;
			NodeList nl = (NodeList)xp.evaluate( xPath, document, XPathConstants.NODESET );

			for ( int i=0; i < nl.getLength(); i++ ){
				Node node = nl.item( i );
				resultado = node.getNodeValue();
				if (!"".equals(resultado))
					break;
			}
			return resultado;
		}finally{

		}
	}
	
	private String getXpath(String xPath) throws Exception {
		try {
			XPath xp = getXPath();
			String resultado = null;
			NodeList nl = (NodeList)xp.evaluate( xPath, new InputSource(new StringReader(pagina.getConteudo())), XPathConstants.NODESET );

			for ( int i=0; i < nl.getLength(); i++ ){
				Node node = nl.item( i );
				resultado = node.getNodeValue();
				if (!"".equals(resultado))
					break;
			}
			return resultado;
		}finally{

		}
	}

	private List<String> getXpathNodelist(String xPath) {
		List<String> resultados =  new ArrayList<String>();
		try {
			XPath xp = getXPath();

			NodeList nl = (NodeList)xp.evaluate( xPath, document, XPathConstants.NODESET );

			for ( int i=0; i < nl.getLength(); i++ ){
				Node node = nl.item( i );
				resultados.add(new String(node.getNodeValue().trim().getBytes(), "UTF-8"));
			}
			return resultados;
		} catch (Exception e) {
			return null;
		}finally{

		}
	}

	public String recuperaItem (String item) throws Exception {
		if("xml".equals(tipo)){
			return getXpath(item);
		}
		
		if("html".equals(tipo)){
			return getXpathHtml(item);
		}
		return "";
		
	}

	public List<String> recuperaListaItens (String item) throws Exception {
		return getXpathNodelist(item);
	}
	
	public Pagina getPagina() {
		return pagina;
	}

	public void setPagina(Pagina pagina) {
		this.pagina = pagina;
	}

}